home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file is part of ixemul.library for the Amiga.
- * Copyright (C) 1991, 1992 Markus M. Wild
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * stat.c,v 1.1.1.1 1994/04/04 04:30:35 amiga Exp
- *
- * stat.c,v
- * Revision 1.1.1.1 1994/04/04 04:30:35 amiga
- * Initial CVS check in.
- *
- * Revision 1.2 1993/11/05 22:03:10 mwild
- * grp/oth support, plus new feature
- *
- * Revision 1.1 1992/05/14 19:55:40 mwild
- * Initial revision
- *
- */
-
- #define _KERNEL
- #include "ixemul.h"
- #include "kprintf.h"
- #include <stdio.h>
- #include <string.h>
- #include "multiuser.h"
-
- /* currently, links are quite buggy.. hope this get cleaned up RSN ;-) */
-
- long fill_stat_mode(struct stat *stb, struct FileInfoBlock *fib)
- {
- long mode;
-
- mode = 0L;
- /* If this is a directory, and Size is not 0, then this is a volume.
- Since the Protection field seems to be random for volumes, we use
- our own flags (= everything readable & writable) */
- if (fib->fib_DirEntryType > 0 && fib->fib_Size != 0)
- fib->fib_Protection = 0xff00;
- stb->st_amode = fib->fib_Protection;
- if (!(fib->fib_Protection & FIBF_EXECUTE))
- mode |= S_IXUSR;
- else if (fib->fib_Protection & FIBF_SCRIPT)
- mode |= S_IXUSR;
- if (!(fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)))
- mode |= S_IWUSR;
- if (!(fib->fib_Protection & FIBF_READ))
- mode |= S_IRUSR;
- #ifdef FIBF_GRP_EXECUTE
- /* FIBF_GRP_EXECUTE requires at least OS3 headers */
- if (fib->fib_Protection & FIBF_GRP_EXECUTE)
- mode |= S_IXGRP;
- if ((fib->fib_Protection & (FIBF_GRP_WRITE|FIBF_GRP_DELETE)) == (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
- mode |= S_IWGRP;
- if (fib->fib_Protection & FIBF_GRP_READ)
- mode |= S_IRGRP;
- if (fib->fib_Protection & FIBF_OTR_EXECUTE)
- mode |= S_IXOTH;
- if ((fib->fib_Protection & (FIBF_OTR_WRITE|FIBF_OTR_DELETE)) == (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
- mode |= S_IWOTH;
- if (fib->fib_Protection & FIBF_OTR_READ)
- mode |= S_IROTH;
- if (fib->fib_Protection & FIBF_HOLD)
- mode |= S_ISTXT;
- if (fib->fib_Protection & muFIBF_SET_UID)
- mode |= S_ISUID;
- if (fib->fib_Protection & muFIBF_SET_GID)
- mode |= S_ISGID;
- #endif
-
- switch (fib->fib_DirEntryType)
- {
- case ST_LINKDIR:
- stb->st_nlink = 3;
- mode |= S_IFDIR;
- break;
- case ST_ROOT:
- case ST_USERDIR:
- stb->st_nlink = 2;
- mode |= S_IFDIR;
- break;
-
- /* at the moment, we NEVER get this entry, since we can't get a lock
- * on a symlink */
- case ST_SOFTLINK:
- mode |= S_IFLNK;
- break;
-
- case ST_PIPEFILE:
- /* don't use S_IFIFO, we don't have a mkfifo() call ! */
- mode |= S_IFCHR;
- break;
-
- case ST_LINKFILE:
- stb->st_nlink = 2;
- mode |= S_IFREG;
- break;
- case ST_FILE:
- default:
- stb->st_nlink = 1;
- mode |= S_IFREG;
- }
-
- /* If a directory is readable, then also allow scanning. */
- if (mode & S_IFDIR)
- mode |= (mode & (S_IRUSR | S_IRGRP | S_IROTH)) >> 2;
- return mode;
- }
-
- static int
- __stat(const char *fname, struct stat *stb, BPTR (*lock_func)())
- {
- BPTR lock;
- struct FileInfoBlock *fib;
- struct InfoData *info;
- int omask, err = 0;
-
- bzero (stb, sizeof(*stb));
-
- omask = syscall (SYS_sigsetmask, ~0);
- stb->st_uid = geteuid();
- stb->st_gid = getegid();
-
- if (!(lock = (*lock_func) (fname, ACCESS_READ)))
- {
- err = IoErr ();
-
- /* take special care of NIL:, /dev/null and friends ;-) */
- if (err == 4242)
- {
- stb->st_mode = S_IFCHR | 0777;
- stb->st_nlink = 1;
- stb->st_blksize = ix.ix_fs_buf_factor * 512;
- stb->st_blocks = 0;
- goto rest_sigmask;
- }
-
- /* take special care of /dev/ptyXX and /dev/ttyXX */
- if (err == 5252)
- {
- stb->st_mode = S_IFCHR | 0777;
- stb->st_nlink = 1;
- stb->st_blksize = ix.ix_fs_buf_factor * 512;
- stb->st_blocks = 0;
- goto rest_sigmask;
- }
-
- /* root directory */
- if (err == 6262)
- {
- stb->st_mode = S_IFDIR | 0777;
- stb->st_nlink = 1;
- stb->st_blksize = ix.ix_fs_buf_factor * 512;
- stb->st_blocks = 0;
- goto rest_sigmask;
- }
-
- KPRINTF (("__stat: lock %s failed, err = %ld.\n", fname, err));
- if (err == ERROR_IS_SOFT_LINK)
- {
- /* provide some default stb.. we can't get anymore info than
- * that. Symlinks should work with Lock(), but till now they
- * don't ;-( */
- stb->st_handler = (int) DeviceProc ((UBYTE *)fname);
- stb->st_dev = (dev_t) stb->st_handler;
- /* HELP! no way to reach the fib of this entry except when
- * scanning the parent directory, but this is NOT acceptable ! */
- stb->st_ino = 123;
- /* this is the most important entry ;-) */
- stb->st_mode = S_IFLNK | 0777;
- stb->st_size = 1024; /* again, this should be available... */
- stb->st_nlink = 1;
- stb->st_rdev = 0;
- /* again, these values ARE accessible, but only by ExNext */
- stb->st_atime = stb->st_mtime = stb->st_ctime = 0;
- stb->st_blksize = stb->st_blocks = 0;
- goto rest_sigmask;
- }
- error:
- syscall (SYS_sigsetmask, omask);
- errno = __ioerr_to_errno (err);
- KPRINTF (("ioerr = %ld, &errno = %lx, errno = %ld\n", err, &errno, errno));
- return -1;
- }
- KPRINTF (("__stat: lock %s ok.\n",fname));
-
- /* alloca() returns stack memory, so it's guaranteed to be word
- * aligned (anything else would be deadly for the sp...) Since DOS needs
- * long aligned data, we'll allocate 1 word more and adjust as needed */
- fib = alloca (sizeof(*fib) + 2);
- /* DON'T use LONG_ALIGN(alloca(..)), the argument is evaluated more than once! */
- fib = LONG_ALIGN (fib);
-
- info = alloca (sizeof(*info) + 2);
- info = LONG_ALIGN (info);
-
- if (!(Examine (lock, fib)))
- {
- __unlock (lock);
- goto error;
- }
-
- stb->st_mode = fill_stat_mode(stb, fib);
-
- /* read the uid/gid data */
- if (muBase)
- {
- stb->st_uid = fib->fib_OwnerUID;
- stb->st_gid = fib->fib_OwnerGID;
- }
-
- /* support for annotated attributes (cool name ;-)) */
- if (! strncmp (fib->fib_Comment, "!SP!", 4))
- {
- int sp_mode, sp_addr;
-
- if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
- stb->st_mode = sp_mode;
- }
-
- /* some kind of a default-size for directories... */
- stb->st_size = fib->fib_DirEntryType < 0 ? fib->fib_Size : 1024;
- stb->st_handler = (long)((struct FileLock *)((long)lock << 2))->fl_Task;
- stb->st_dev = (dev_t)stb->st_handler; /* trunc to 16 bit */
- /* The fl_Key field of the FileLock structure is always unique. This is
- also true for filesystems like AFS and AFSFloppy. Thanks to Michiel
- Pelt (the AFS author) for helping me with this. */
- stb->st_ino = (ino_t)((struct FileLock *)(BTOCPTR(lock)))->fl_Key;
- stb->st_atime =
- stb->st_ctime =
- stb->st_mtime = (8*365+2)*24*3600 + ix_get_gmt_offset() +
- fib->fib_Date.ds_Days * 24 * 60 * 60 +
- fib->fib_Date.ds_Minute * 60 +
- fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
- /* in a try to count the blocks used for filemanagement, we add one for
- * the fileheader. Note, that this is wrong for large files, where there
- * are some extension-blocks as well */
- stb->st_blocks = fib->fib_NumBlocks + 1;
-
- bzero (info, sizeof (*info));
- stb->st_blksize = 0;
- if (Info(lock, info))
- {
- /* optimal for fileio is as high as possible ;-) This is a
- * compromise between "as high as possible" and not too restricitve
- * for people low on memory */
- stb->st_blksize = info->id_BytesPerBlock * ix.ix_fs_buf_factor;
- stb->st_blocks = (stb->st_blocks * info->id_BytesPerBlock) / 512;
- }
-
- if (! stb->st_blksize) stb->st_blksize = 512;
-
- __unlock (lock);
-
- rest_sigmask:
- syscall (SYS_sigsetmask, omask);
- return 0;
- }
-
- /***************************************************************************/
-
- int
- stat (const char *fname, struct stat *stb)
- {
- return __stat (fname, stb, __lock);
- }
-
- int
- lstat (const char *fname, struct stat *stb)
- {
- return __stat (fname, stb, __llock);
- }
-
- int
- filenamecmp(const char *fname)
- {
- BPTR lock;
- struct FileInfoBlock *fib;
- int omask, result = 0;
-
- omask = syscall (SYS_sigsetmask, ~0);
-
- if (!(lock = __llock((char *)fname, ACCESS_READ)))
- {
- syscall (SYS_sigsetmask, omask);
- return 0;
- }
-
- fib = alloca (sizeof(*fib) + 2);
- fib = LONG_ALIGN (fib);
-
- /* Only reject this filename if:
- *
- * 1) fname differs from fib_FileName (case sensitive compare)
- *
- * AND
- *
- * 2) compared case insensitively, fname is equal to fib_FileName.
- *
- * Test 2 is needed for links (both hard and soft), since it is
- * impossible to get the name of the link with Examine. Only
- * ExAll/ExNext can obtain the link name.
- */
-
- if (Examine (lock, fib))
- result = strcmp(basename((char *)fname), fib->fib_FileName) &&
- !stricmp(basename((char *)fname), fib->fib_FileName);
- __unlock (lock);
- syscall (SYS_sigsetmask, omask);
- return result;
- }
-